package com.autonavi.abs.common.aop.aspect;

import com.autonavi.abs.common.aop.annotation.ParamValidation;
import com.autonavi.abs.common.exception.MessageException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author tianquan.ld
 * @version V1.0
 * <p>Description: 参数校验aspect
 * * 【注意】仅适用于POJO类型
 * </p>
 * @date 2020-07-10 19:52
 */
@Component
@Aspect
public class ParamValidationAspect {

    private final static Logger LOGGER = LoggerFactory.getLogger(ParamValidationAspect.class);

    @Pointcut(value = "@annotation(com.autonavi.abs.common.aop.annotation.ParamValidation)")
    public void pointcut() {

    }

    @Before(value = "pointcut() && @annotation(paramValidation)")
    public void validate(JoinPoint jp, ParamValidation paramValidation) {

        Object[] paramArray = jp.getArgs();
        if (ArrayUtils.isEmpty(paramArray)) {
            return;
        }

        // 待校验的类型
        Class checkClazz = paramValidation.clazz();
        List<Object> paramList = Stream.of(paramArray).filter((param) -> {
            Class clazz = param.getClass();
            return clazz.equals(checkClazz);
        }).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(paramList)) {
            throw new MessageException("未发现需要校验的内容");
        }

        StringBuilder builder = new StringBuilder();
        try {

            // 校验结果
            paramList.stream().forEach((obj) -> {
                Set<ConstraintViolation<Object>> validateSet = Validation.buildDefaultValidatorFactory()
                        .getValidator().validate(obj);
                if (!CollectionUtils.isEmpty(validateSet)) {
                    String messages = validateSet.stream()
                            .map(ConstraintViolation::getMessage)
                            .reduce((m1, m2) -> m1 + ";" + m2)
                            .orElse("");
                    builder.append(messages);
                }
            });

        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }

        String warning = builder.toString();
        if (StringUtils.isNotBlank(warning)) {
            // 抛出exception，需要拦截处理
            throw new MessageException(builder.toString());
        }

    }

}
